//shared_ptr共享它所指向对象，多个shared_ptr可以指向(又叫关联)相同的对象
//当新的shared_ptr与该对象关联时，引用计数增加1
//shared_ptr超出作用域时，引用计数-1,当引用计数为0时，释放该对象


#include<memory>
#include<iostream>
#include<string>
#include<vector>
using namespace std;

class AA
{
public:
	AA()
	{
		cout << m_name << "调用构造函数AA()。" << endl;
	}
	
	AA(const string& name) :m_name(name)
	{
		cout << "调用构造函数AA(" << m_name << ") " << endl;	// "<<变量名<<"
	}
	
	~AA()
	{
		cout << "调用了析构函数~AA(" << m_name << ")" << endl;
	}
	string m_name;
	
};

void func(shared_ptr<AA> pu)
{
	cout << "func:" << endl;
	cout << "&pu: "<< &pu << endl;
	cout << "pu->name : " << pu->m_name << endl;
	pu->m_name = "Lucy";
	cout << "pu->name :" << pu->m_name << endl;
	cout << "pu.use_count():" << pu.use_count() << endl;
}

int main()
{	
	//初始化 和unique_ptr相同
	//法一
	shared_ptr<AA> pu1(new AA("李四"));
	//法二
	shared_ptr<AA> pu2 = make_shared<AA>("王五");	//推荐
	//法三
	AA* p = new AA("张三");
	shared_ptr<AA>  pu3(p);
	//法四，拷贝构造
	shared_ptr<AA> pu4 = pu1;	//用已存在的shared_ptr拷贝构造，引用计数加1
	
	cout << pu4.use_count() << endl;	//此时pu4和pu1的值一样，引用计数也一样
	cout << pu4.get() << endl;
	cout << pu1.get() << endl;		//并且原始指针也一样
	
	//.use_count() //显示引用计数的值
	cout << "pu1.use_count() = " << pu3.use_count() << endl;
	




	//基本用法：
	//shared_ptr没有删除拷贝构造和赋值函数
	
	//.unique()		//如果引用计数use_count()为1，则返回true， 否则返回false
	//.get()		//返回裸指针
	//shared_ptr只能管理new分配的内存（即堆区），同unique_ptr
	
	//不能同一个裸指针初始化多个shared_ptr，同unique_ptr，多次释放同一个裸指针，相当于操作野指针
	//但多个shared_ptr可以共享同一个对象



	//shared_ptr支持赋值(=)，左值的shared_ptr的计数器将减一，右值的shared_ptr的计数器将加一
	
	shared_ptr<AA> pa0(new AA("张三"));
	shared_ptr<AA> pa1 = pa0;
	shared_ptr<AA> pa2 = pa0;
	cout << "pa0.use_count() = " << pa0.use_count();	//值为3

	shared_ptr<AA> pb0(new AA("李四"));
	shared_ptr<AA> pb1 = pb0;
	cout << "pb0.use_count() = " << pb0.use_count() << endl;	//值为2

	pb1 = pa1;	//pb1为左值， pa1为右值
	//pb0 = pa1;	//若加这一条语句，则没有指针指向李四，释放资源
	cout << "pa0.use_count() = " << pa0.use_count() << endl;	//值为4
	cout << "pb0.use_count() = " << pb0.use_count() << endl;	//值为1
	
	
	
	
	//当shared_ptr指针作为函数参数时
	//1.传引用(可以传值，因为shared_ptr有构造函数)
	//2.传地址，很少用，不方便
	//3.传裸指针

	shared_ptr<AA> pu1(new AA("David"));
	func(pu1);
	cout << "main: " << endl;
	cout << "pu1->m_name: " << pu1->m_name << endl;
	cout << "&pu1: " << &pu1 << endl;
	cout << "pu1.use_count(): " << pu1.use_count() << endl;
	//和普通指针一样，值传递时会先拷贝构造一个新的shared_ptr，但所指向的对象相同，所以都可以修改



	//shared_ptr指针不支持的运算（+， -， ++, --）
	
	
	//用nullptr给shared_ptr赋值会将引用计数-1，如果引用计数为0，则会释放shared_ptr
	//空的shared_ptr == nullptr


	//.move()还可以将unique_ptr转移为shared_ptr，反之不行

	//如果unique_ptr可以解决问题就不用shared_ptr,unique_ptr效率高，占资源少
	
	
	
	//shared_ptr的线程安全性
		//shared_ptr的引l用计数本身是线程安全（引l用计数是原子操作）。
		//多个线程同时读同一个 shared_ptr对象是线程安全的。
		//如果是多个线程对同一个shared_ptr对象进行读和写，则需要加锁。
		//多线程读写shared_ptr 所指向的同一个对象，不管是相同的shared_ptr对象，还是不同的shared_ptr 对象，也需要加锁保护。

	return 0;
}






//shared_ptr存在的问题
//shared_ptr内部维护了一个共享的引用计数器，多个shared_ptr可以指向同一个资源
//如果出现了循环引用的请款，引用计数器则无法归0，资源不会被释放

#include<memory>
#include<iostream>
#include<string>
#include<vector>
#include<functional>
using namespace std;
class BB;	//声明一下BB类
class AA
{
public:
	AA()
	{
		cout << m_name << "调用构造函数AA()。" << endl;
	}

	AA(const string& name) :m_name(name)
	{
		cout << "调用构造函数AA(" << m_name << ") " << endl;	// "<<变量名<<"
	}

	~AA()
	{
		cout << "调用了析构函数~AA(" << m_name << ")" << endl;
	}
	string m_name;
	shared_ptr<BB> m_p;
};

class BB
{
public:
	string m_name;
	shared_ptr<AA> m_p;
	BB()
	{
		cout << "调用构造函数BB()。" << endl;
	}
	BB(const string& name) :m_name(name)
	{
		cout << "调用构造函数BB(" << m_name << ")。" << endl;
	}
	~BB()
	{
		cout << "调用析构函数~BB(" << m_name << ")。" << endl;
	}
};

int main()
{
	shared_ptr<AA> pa = make_shared<AA>("Tom");
	shared_ptr<BB> pb = make_shared<BB>("Jerry");

	pa->m_p = pb;	//AA类的m_p成员指向BB类资源
	pb->m_p = pa;	//BB类的m_p成员指向AA类资源
	//运行结果不会调用析构函数

	return 0;
}
//如何解决这一问题需要用到weak_ptr


